"""
# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.

# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

=================================================

Day 6作业 - 编写炸金花游戏程序
-------------------------------------------------
一副去掉大小王的扑克牌,自己写一个程序，实现发牌、比大小判断输赢。
`````````````````````````````````````````````````
- 每个人一开始都摸三张牌
- **炸金花中，最大的牌是A,从K开始逐渐变小,最小的牌是2**
- 有以下几种牌：

   - 豹子：三张一样的牌，如3张6.
   - 顺金：又称同花顺，即3张同样花色的顺子，如红桃 5、6、7
   - 顺子：又称拖拉机，花色不同，但是顺子，如红桃5、方片6、黑桃7，组成的顺子
   - 对子：2张牌一样
   - 单张：单张最大的是A

- 这几种牌模型的大小顺序为， **豹子>顺金>顺子>对子>单张**
- 需程序实现的点：

    - 先生成一付完整的扑克牌
    - 给5个玩家随机发牌
    - 统一开牌，比大小，输出赢家是谁

        - <3张牌从大到小排序然后再比较大小>

            -    ♠♥♦♣♣
            -    **♦8  ♥J  ♠K**
            -    **♠9  ♦10 ♣A**
        - <单牌之间如何比大小>

            -    **第3牌为[2->A],权重1,分数即[2,14]**
            -    **第2牌为[2->A],权重10,分数即[20,140]**
            -    **第1牌为[2->A],权重100,分数即[200,1400]**
        - <不同牌模型如何比大小>

            -    **单牌[222->AAA],权重1,分数即[222,1400+140+14=1554]**
            -    **对子[222->AAA],权重10,分数即[(2*100+2)*10=2020,(1400+14)*10=14140]**
            -    **顺子[234->QKA],权重100,分数即[22200,155400]**
            -    **金花[222->AAA],权重1000,分数即[222000,1554000]**
            -    **顺金[222->AAA],权重10000,分数即[2220000,15540000]**
            -    **豹子[222->AAA],权重100000,分数即[22200000,155400000]**
- 游戏规则：

    - 首先，炸金花需要的只是一副去掉大小王的扑克牌，人数从两个到六个都可以玩。
    - 每个人一开始都摸三张牌，之后和一位玩家比牌，每个人都要进行下注。在比牌的时候不能看到相互的牌，结束之后才能看到手牌。
    - 最终胜利的人可以继续和下一个人进行比牌。那么，比牌应该怎么比呢？
    - 炸金花里的牌型有很多种。第一种是豹子，它代表的是三张一样的牌；
    - 第二种牌顺金，表示的是三张花色相同的顺子。如果是三张不同花色的顺子，则为顺子。
    - 三张花色相同的牌称为金花。如果如果有两张一样的牌则称有对子；
    - 除了上面这些情况之外，还有一种情况是拿到三根散牌，既不是顺子也不是对子，这样的牌称为单张。
    - 在牌的大小中，豹子最大，其次是顺金、金花、顺子、对子，最小的牌是单张。
    - 炸金花中，最大的牌是A，由A组成的各种类型的牌都是最大的，之后，
    - 从K开始逐渐变小，最小的牌是2，如果出现相同的牌型的话，则比这类牌型的大小，
    - 再相同的话，就比下一种牌型的大小。如果两个人的牌一样的话，则先比牌的人获胜。
    - 一付扑克牌，去掉大小王，每个玩家发 3张牌，最后比大小，看谁赢。
"""
import random

import faker


def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.


def generate_poke_list(poke_count, shuffle=True):
    poke_types = "♥♦♣♠"
    poke_nums = [2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K", "A"]
    poke_list = []
    for _ in range(poke_count):
        count = 2
        for p_num in poke_nums:
            for p_type in poke_types:
                card = [f"{p_type}{p_num}", count]
                poke_list.append(card)
            count += 1
    if shuffle:
        random.shuffle(poke_list)
        for _ in poke_list:
            r = random.randint(0, len(poke_types) * len(poke_nums) * poke_count - 1)
            (poke_list[0], poke_list[r]) = (poke_list[r], poke_list[0])
    print(f"{len(poke_list,)=}")
    # print(f"{(poke_list,)=}")
    return poke_list


def issue_cards(poke_list, players):
    players_dict = {}
    (start, end) = (0, 3)
    p_cards = random.sample(poke_list, 3 * len(players))
    # print(f"{p_cards=}")
    for p_name in players:
        players_dict[p_name] = p_cards[start:end]
        (start, end) = (start + 3, end + 3)
        # print("为玩家 %12s 生成了牌 %s" % (p_name, players_dict[p_name]))
    return players_dict


def sort_by_value2(lis):
    for pos in range(len(lis)):
        for test in range(pos + 1, len(lis)):
            if (lis[test][1]) < lis[pos][1]:
                lis[test], lis[pos] = lis[pos], lis[test]
    return lis


def calc_single(p_cards, score=0):
    weight_singe = [1, 10, 100]
    count = 0
    p_cards = sort_by_value2(p_cards)
    for card in p_cards:
        score += card[1] * weight_singe[count]
        count += 1
    return score


def calc_pair(p_cards, score=0):
    p_cards = sort_by_value2(p_cards)
    card_vales = [card[1] for card in p_cards]  # 列表推导式
    if len(set(card_vales)) == 2:
        if card_vales[0] == card_vales[1]:
            score = card_vales[0] * 100 + card_vales[2]
        else:
            score = card_vales[2] * 100 + card_vales[0]
        return score * 10
    return score


def calc_straight(p_cards, score=0):
    p_cards = sort_by_value2(p_cards)
    (a, b, c) = [card[1] for card in p_cards]
    if b - a == 1 and c - b == 1 or (a, b, c) == (2, 3, 14):
        return score * 100
    return score


def calc_same_color(p_cards, score=0):
    """
    + **同花顺的逻辑已经包含在同花和顺子中了**
    + **同花>顺子:score * 1000**

    :param p_cards: 待计算的牌
    :param score: 分数
    :return: 计算好的分数
    """
    colors = {card[0][0] for card in p_cards}
    if len(colors) == 1:
        return score * 1000
    return score


def calc_same_color_straight(p_cards, score=0):
    """
    + **同花顺的逻辑已经包含在同花和顺子中了**
    + **同花顺:score * 10000 即 score / 10**

    :param p_cards: 待计算的牌
    :param score: 分数
    :return: 计算好的分数
    """
    p_cards = sort_by_value2(p_cards)
    (a, b, c) = [card[1] for card in p_cards]
    colors = {card[0][0] for card in p_cards}
    if b - a == 1 and c - b == 1 or (a, b, c) == (2, 3, 14):
        if len(colors) == 1:
            return score / 10
    return score


def calc_leopard(p_cards, score=0):
    """
    + **同花豹子的逻辑已经包含在同花和豹子中了**

    :param p_cards: 待计算的牌
    :param score: 分数
    :return: 计算好的分数
    """
    card_values = {card[1] for card in p_cards}
    if len(card_values) == 1:
        return score*100000
    return score


def calc_cards(p_cards):
    score = 0
    calc_funs = [calc_single, calc_pair, calc_straight, calc_same_color, calc_same_color_straight, calc_leopard]
    for fun in calc_funs:
        res = fun(p_cards, score)
        if res > score:
            score = res
    return score


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('PyCharm')
    names = faker.Faker(locale="zh_CN")
    players = set()
    for i in range(4):
        players.add(names.name())

    poke_list = generate_poke_list(1)
    players_dict = issue_cards(poke_list, players)
    players_score = []
    for p_name in players:
        score = calc_cards(players_dict[p_name])
        p_name1 = "%4s" % p_name
        players_score.append([p_name, score])
        str1 = "%9s\t 分数:%10s 手牌:%s" % (p_name, score, sort_by_value2(players_dict[p_name]))
        print(str1)
    players_score = sort_by_value2(players_score)
    winner_list = set()
    for player_score in players_score:
        if player_score[1] == players_score[-1][1]:
            winner_list.add(player_score[0])
    print(f"{winner_list=}")
    # p_cards = [['♥4', 4], ['♥4', 4], ['♥7', 7]]  # 两副牌同花对子4070000
    # p_cards = [['♥4', 4], ['♥5', 5], ['♥7', 7]]  # 同花754000
    # p_cards = [['♦5', 5], ['♥6', 6], ['♥7', 7]]  # 顺子76500
    # print(calc_cards(p_cards))

    # EOF
